package com.ms.base.jdbc.datasource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * <b>description</b>：数据源自动配置类 <br>
 * <b>time</b>：2018-07-26 13:03 <br>
 * <b>author</b>： ready likun_557@163.com
 */
@Configuration
@EnableConfigurationProperties(DsProperties.class)
@AutoConfigureBefore(DataSourceAutoConfiguration.class) //在DataSourceAutoConfiguration之前进行加载
@ConditionalOnProperty(prefix = DsProperties.PREFIX, name = "enabled", matchIfMissing = true)
public class DsAutoConfiguration {

    private DsProperties dsProperties;

    public DsAutoConfiguration(DsProperties dsProperties) {
        this.dsProperties = dsProperties;
    }

    @Bean(name = "masterDataSource")
    @ConfigurationProperties(prefix = DsProperties.PREFIX + ".master")
    public DataSource masterDataSource() {
        return DataSourceBuilder.create().type(this.dsProperties.getDsType()).build();
    }

    @Bean(name = "slaveDataSource")
    @ConfigurationProperties(prefix = DsProperties.PREFIX + ".slave")
    public DataSource slaveDataSource() {
        return DataSourceBuilder.create().type(this.dsProperties.getDsType()).build();
    }

    @Bean(name = "dataSource")
    @DependsOn({"masterDataSource", "slaveDataSource"})
    public DataSource dataSource() {
        DataSource masterDataSource = this.masterDataSource();
        DataSource slaveDataSource = this.slaveDataSource();
        MasterSlaveDataSource masterSlaveDataSource = new MasterSlaveDataSource();
        masterSlaveDataSource.setDefaultTargetDataSource(masterDataSource);
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(null, masterDataSource);
        targetDataSources.put(DsType.MASTER, masterDataSource);
        targetDataSources.put(DsType.SLAVE, slaveDataSource);
        masterSlaveDataSource.setTargetDataSources(targetDataSources);
        return masterSlaveDataSource;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(this.dataSource());
        bean.setConfigLocation(new ClassPathResource("/mybatis/config.xml"));
        return bean.getObject();
    }

    @Bean(name = "transactionManager")
    public DataSourceTransactionManager transactionManager() {
        DataSource dataSource = this.dataSource();
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean
    public DsInterceptor dsInterceptor() {
        return new DsInterceptor();
    }
}